/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */


import org.workplicity.util.Logger;
import org.workplicity.task.NetTask;
import org.workplicity.util.Helper;
import org.workplicity.worklet.WorkletContext;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import org.workplicity.entry.Service;
import org.workplicity.entry.User;
import org.workplicity.entry.WorkRequest;
import org.workplicity.entry.WorkSlate;
import org.workplicity.entry.event.Event;

/**
 * @author Stephen Horn & Elliott Picker
 */
public class Warn {

    private final static String URL_BASE =
            "http://localhost:8080/netprevayle/task";
    /**
     * This is the worklet context to utilize the Helper pattern.
     */
    private static WorkletContext context = WorkletContext.getInstance();

    /**
     * NetTest entry point for the JVM
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        try {
            // Disable logging which goes to the console.
            Logger.setEnabled(false);

            // Set the host to use.
            NetTask.setUrlBase(URL_BASE);

            // Login using the admin account with the default
            // log name and password
            if (!Helper.login("admin", "gaze11e", context)) {
                throw new Exception("login failed");
            }


        } catch (Exception e) {
            System.out.println(e);
        }
    }

    /**
     * This method checks the Accounts repository for duplicate user Lognames
     * @param users an ArrayList of all users
     * @return an ArrayList containing the User objects which have duplicate Lognames
     */
    public static ArrayList checkDuplicateNames(ArrayList<User> users) {

        //The duplicates ArrayList is the ArrayList in which users found to be
        //duplicates will be stored
        ArrayList duplicates = new ArrayList<User>();

        //This for loop iterates through the users, comparing them to each other
        for (int outer = 0; outer < users.size() - 1; outer++) {
            //suspect is user which will be compared to each other user
            User suspect = users.get(outer);
            //The inner for loop retrieves each user in the list of users after
            //the suspect user and compares their lognames. If a duplicate is
            //found, it is added to the duplicates ArrayList.
            for (int inner = outer + 1; inner < users.size(); inner++) {
                if (suspect.getLogname().equals(users.get(inner).getLogname())) {
                    duplicates.add(suspect);
                }
            }
        }
        return duplicates;
    }

    /**
     * This method checks to see if any user has no Services
     * @param users an ArrayList of all users
     * @return an ArrayList containing the User objects which do not have Services
     */
    public static ArrayList checkUserNoService(ArrayList<User> users) {

        //The warnings ArrayList will contain the User objects which do not have
        //any services
        ArrayList warnings = new ArrayList<User>();
        //This for loop will iterate through the list of users, checking the size
        //of each user's ServiceList. If empty, that user will be added to warnings.
        for (int i = 0; i < users.size(); i++) {
            User suspect = users.get(i);
            if (suspect.getServiceList().isEmpty()) {
                warnings.add(suspect);
            }
        }
        return warnings;
    }

    /**
     * This method checks to see if there are any Services which do not have users
     * @param services an ArrayList of all services
     * @param users an ArrayList of all users
     * @return an ArrayList containing the Services which do not have users
     */
    public static ArrayList checkServiceNoUser(ArrayList<Service> services, ArrayList<User> users) {

        //This for loop iterates through the list of users
        for (int outer = 0; outer < users.size(); outer++) {
            //serviceCheck contains the unique ids of the current user's ServiceList
            List<Integer> serviceCheck = users.get(outer).getServiceList();
            //The inner for loop iterates through the list of all services. If
            //the current user's ServiceList contains any service from the list of
            //all services, that service is removed from that list. This effectively
            //removes any service which has a user from the original list, leaving
            //only those that do not contain any users to be returned.
            for (int inner = 0; inner < services.size(); inner++) {
                if (serviceCheck.contains(services.get(inner).getId())) {
                    services.remove(inner);
                }
            }
        }
        return services;
    }

    /**
     * This method checks if any user has an invalid or missing Logname
     * @param users an ArrayList of all users
     * @return an ArrayList of the users which have invalid or missing Lognames
     */
    public static ArrayList<User> invalidLogname(ArrayList<User> users) {

        //The warnings ArrayList will contain users who have an invalid or
        //missing logname
        ArrayList<User> warnings = new ArrayList<User>();
        //The INVALID string contains the characters which, if contained by a
        //user's logname, cause the logname to be considered invalid
        String INVALID = " !_@#$%&*[](){}:;\"\'<>?/~.,`";

        //This for loop iterates through the list of users
        for (int outer = 0; outer < users.size(); outer++) {
            //currentUser is the user at the current iteration of the for loop
            User currentUser = users.get(outer);
            //logname is the Logname of the current user
            String logname = currentUser.getLogname();
            //The inner for loop checks to see if the current logname contains
            //any characters found in the string INVALID
            for (int inner = 0; inner < INVALID.length(); inner++) {
                if (logname.indexOf(INVALID.charAt(inner)) != -1) {
                    warnings.add(currentUser);
                }
            }
        }

        //This for loop checks to see if any user's logname is equal to an empty
        //string, which would cause its logname to be considered missing
        for (int loop = 0; loop < users.size(); loop++) {
            User currentUser = users.get(loop);
            String logname = currentUser.getLogname();
            if (logname.equals("")) {
                warnings.add(currentUser);
            }
        }
        return warnings;
    }

    /**
     * This method checks user password to see if they are invalid or insecure
     * @param users an ArrayList of all users
     * @return an ArrayList of the users whose password are invalid or insecure
     */
    public static ArrayList<User> invalidPassword(ArrayList<User> users) {

        //The warnings ArrayList will contain users who have an invalid or
        //insecure password
        ArrayList<User> warnings = new ArrayList<User>();
        //The INVALID string contains the characters which, if contained by a
        //user's password, cause the password to be considered invalid
        String INVALID = " !_@#$%&*[](){}:;\"\'<>?/~.,`";

        //This for loop iterates through the list of users
        for (int outer = 0; outer < users.size(); outer++) {
            //currentUser is the user at the current iteration of the for loop
            User currentUser = users.get(outer);
            //password is the Password of the current user
            String password = currentUser.getPassword();
            //This if statement determines if a password is too short
            if (password.length() < 3) {
                warnings.add(currentUser);
                continue;
            }
            //This if statement checks if the user's password is equal to their
            //logname
            if (password.equals(currentUser.getLogname())) {
                warnings.add(currentUser);
                continue;
            }
            //The inner for loop checks to see if the current password contains
            //any characters found in the string INVALID
            for (int inner = 0; inner < INVALID.length(); inner++) {
                if (password.indexOf(INVALID.charAt(inner)) != -1) {
                    warnings.add(currentUser);
                }
            }
        }
        return warnings;
    }

    /**
     * This method looks through the repositories and determines if any entries have identical Ids
     * @param CHlist an ArrayList representing the ClearingHouse repository
     * @param SRlist an ArrayList representing the Services repository
     * @param WSlist an ArrayList representing the WorkSlates repository
     * @param AClist an ArrayList representing the Accounts repository
     * @param FUlist an ArrayList representing the Futures repository
     * @return a list of strings of the names of entries that have identical ids, seperated by titles of which repository they were found in
     */
    public static ArrayList<String> duplicateIds(ArrayList<WorkRequest> CHlist, ArrayList<Service> SRlist, ArrayList<WorkSlate> WSlist, ArrayList<User> AClist, ArrayList<Event> FUlist) {
        ArrayList<String> duplicates = new ArrayList<String>();
        //label which repository the duplicates were found in
        duplicates.add("WorkSlates");
        //Check if any workslates have identical ids

        for (int outer = 0; outer < WSlist.size() - 1; outer++) {
            for (int inner = outer + 1; inner < WSlist.size(); inner++) {
                if (WSlist.get(inner).getId().equals(WSlist.get(outer).getId())) {
                    duplicates.add(WSlist.get(inner) + " and " + WSlist.get(outer));
                }
            }
        }
        //label which repository the duplicates were found in
        duplicates.add("Accounts");
        // Check if any users have identical ids

        for (int outer = 0; outer < AClist.size() - 1; outer++) {
            for (int inner = outer + 1; inner < AClist.size(); inner++) {
                if (AClist.get(inner).getId().equals(AClist.get(outer).getId())) {
                    duplicates.add(AClist.get(inner) + " and " + AClist.get(outer));
                }
            }
        }
        //label which repository the duplicates were found in
        duplicates.add("Services");
        // Check if any services have identical ids

        for (int outer = 0; outer < SRlist.size() - 1; outer++) {
            for (int inner = outer + 1; inner < SRlist.size(); inner++) {
                if (SRlist.get(inner).getId().equals(SRlist.get(outer).getId())) {
                    duplicates.add(SRlist.get(inner) + " and " + SRlist.get(outer));
                }
            }
        }
        //label which repository the duplicates were found in
        duplicates.add("ClearingHouse");
        // Check if any requests have identical ids
        for (int outer = 0; outer < CHlist.size() - 1; outer++) {
            for (int inner = outer + 1; inner < CHlist.size(); inner++) {
                if (CHlist.get(inner).getId().equals(CHlist.get(outer).getId())) {
                    duplicates.add(CHlist.get(inner) + " and " + CHlist.get(outer));
                }
            }
        }
        //label which repository the duplicates were found in
        duplicates.add("Futures");
        // Check if any events have identical ids

        for (int outer = 0; outer < FUlist.size() - 1; outer++) {
            for (int inner = outer + 1; inner < FUlist.size(); inner++) {
                if (FUlist.get(inner).getId().equals(FUlist.get(outer).getId())) {
                    duplicates.add(FUlist.get(inner) + " and " + FUlist.get(outer));
                }
            }
        }

        return duplicates;

    }

    /**
     * This method looks through the ClearingHouse repository and makes sure all the services the requests refrence are in fact valid
     * @param REQlist an ArrayList representing the ClearingHouse repository
     * @param SERlist an ArrayList representing the Services repository
     * @return a list of the WorkRequests that are not valid
     */
    public static ArrayList<WorkRequest> ReqsWithInvalidServices(ArrayList<WorkRequest> REQlist, ArrayList<Service> SERlist) {
        ArrayList<WorkRequest> reqs = new ArrayList<WorkRequest>();

        for (int req = 0; req < REQlist.size(); req++) {
            Integer servID = REQlist.get(req).getServiceId();
            boolean isValid = false;
            for (int ser = 0; ser < SERlist.size(); ser++) {
                if (servID.equals(SERlist.get(ser).getId())) {
                    isValid = true;
                }
            }
            if (!isValid) {
                reqs.add(REQlist.get(req));
            }

        }
        return reqs;
    }

    /**
     * This method looks through the Futures repository and makes sure all the templates are valid
     * @param futures an ArrayList representing the futures repository
     * @return a list of the Futures that do not have valid templates
     */
    public static ArrayList<Event> futuresInvalidTemplates(ArrayList<Event> futures) {
        ArrayList<Event> invalids = new ArrayList<Event>();
        for (int index = 0; index < futures.size(); index++) {
            if (futures.get(index).getTemplate() == null) {
                invalids.add(futures.get(index));
            }
        }
        return invalids;
    }

    /**
     * This method looks through the Futures repository and checks if any futures are both enabled and expired
     * @param futures an ArrayList representing the futures repository
     * @return a list of the Futures that are both enabled and expired
     */
    public static ArrayList<Event> enabledAndExpired(ArrayList<Event> futures) {
        ArrayList<Event> eAndE = new ArrayList<Event>();
        for (int index = 0; index < futures.size(); index++) {
            if (futures.get(index).getEnabled() && futures.get(index).getLastFired().before(Calendar.getInstance().getTime())) {
                eAndE.add(futures.get(index));
            }
        }
        return eAndE;
    }
}
